﻿using System;
using System.Collections.Generic;
using Assist;
using Autodesk.Revit.DB;
using YJKGeometryFuncs;

namespace YJKArchBaseCode.OutWallSearch
{
	public class WallData
	{
		public EdgeInfo PositiveLine
		{
			get
			{
				return this.m_PositiveLine;
			}
		}

		public EdgeInfo NegativeLine
		{
			get
			{
				return this.m_NegativeLine;
			}
		}

		public EdgeInfo CenterLine
		{
			get
			{
				return this.m_CenterLine;
			}
		}

		public Document Doc
		{
			get
			{
				return this.m_Doc;
			}
		}

		public ElementId Id
		{
			get
			{
				return this.m_Id;
			}
		}

		public bool FindedPositive
		{
			get
			{
				return this.m_FindedPositive;
			}
		}

		public bool FindedNegative
		{
			get
			{
				return this.m_FindedNegative;
			}
		}

		public WallData(WallData rhs)
		{
			this.m_PositiveLine = rhs.m_PositiveLine;
			this.m_NegativeLine = rhs.m_NegativeLine;
			this.m_CenterLine = rhs.m_CenterLine;
			this.m_Doc = rhs.m_Doc;
			this.m_Id = rhs.m_Id;
		}

		public WallData(EdgeInfo positiveLine, EdgeInfo negativeLine, EdgeInfo centerLine, Autodesk.Revit.DB.Document doc, ElementId id)
		{
			this.m_PositiveLine = positiveLine;
			this.m_NegativeLine = negativeLine;
			this.m_CenterLine = centerLine;
			this.m_Doc = doc;
			this.m_Id = id;
		}

		public bool IsOutWall(ref WallData.OutWallOrientations orientations)
		{
			if (this.m_FindedPositive && !this.m_FindedNegative)
			{
				orientations = WallData.OutWallOrientations.OWO_Positive;
				return true;
			}
			if (this.m_FindedNegative && !this.m_FindedPositive)
			{
				orientations = WallData.OutWallOrientations.OWO_Negative;
				return true;
			}
			if (this.m_FindedNegative && this.m_FindedPositive)
			{
				double val = this.CenterLine.Length() / 2.0;
				orientations = WallData.OutWallOrientations.OWO_Two_Sided;
				using (List<EdgeInfo>.Enumerator enumerator = this.GetOutWallSegmentCenterLine().GetEnumerator())
				{
					while (enumerator.MoveNext())
					{
						if (Geometry.GreaterThan(enumerator.Current.Length(), val))
						{
							return true;
						}
					}
				}
				return false;
			}
			orientations = WallData.OutWallOrientations.OWO_None;
			return true;
		}

		public bool IsOutWallWithCenterLineSegment(Curve wallCenterLineSegment)
		{
			WallData.OutWallOrientations outWallOrientations = WallData.OutWallOrientations.OWO_None;
			return this.IsOutWallWithCenterLineSegment(wallCenterLineSegment, ref outWallOrientations);
		}

		public bool IsOutWallWithCenterLineSegment(Curve wallCenterLineSegment, ref WallData.OutWallOrientations orientations)
		{
			orientations = WallData.OutWallOrientations.OWO_None;
			EdgeInfo segment = new EdgeInfo(wallCenterLineSegment);
			if (!this.FindedOverlapSegementLine(segment, this.m_FindedPositiveLineSegments))
			{
				orientations = WallData.OutWallOrientations.OWO_Positive;
				return true;
			}
			if (!this.FindedOverlapSegementLine(segment, this.m_FindedNegativeLineSegments))
			{
				orientations = WallData.OutWallOrientations.OWO_Negative;
				return true;
			}
			return false;
		}

		public List<EdgeInfo> GetOutWallSegmentCenterLine()
		{
			List<EdgeInfo> list = new List<EdgeInfo>();
			foreach (EdgeInfo edgeInfo in this.m_FindedNegativeLineSegments)
			{
				if (!this.FindedOverlapSegementLine(edgeInfo, this.m_FindedPositiveLineSegments))
				{
					list.Add(edgeInfo);
				}
			}
			foreach (EdgeInfo edgeInfo2 in this.m_FindedPositiveLineSegments)
			{
				if (!this.FindedOverlapSegementLine(edgeInfo2, this.m_FindedNegativeLineSegments))
				{
					list.Add(edgeInfo2);
				}
			}
			return list;
		}

		private bool FindedOverlapSegementLine(EdgeInfo segment, List<EdgeInfo> referenceSegments)
		{
			double val = AssistFunc.mmToFeet(50.0);
			foreach (EdgeInfo edgeInfo in referenceSegments)
			{
				XYZ xyz = null;
				XYZ xyz2 = null;
				Geometry.OverlapType overlapType = OverlapFinder.OverlapFind(segment, edgeInfo, ref xyz, ref xyz2);
				if (overlapType != Geometry.OverlapType._OT_None && overlapType != Geometry.OverlapType._OT_Linked)
				{
					double val2 = xyz.DistanceTo(xyz2);
					if (segment.IsArc)
					{
						double bulge = Geometry.GetBulge(xyz, xyz2, segment.Center, true);
						val2 = new EdgeInfo(xyz, xyz2, bulge).Length();
					}
					if (!Geometry.LessThan(val2, val))
					{
						return true;
					}
				}
			}
			return false;
		}

		public void SetFindedInfos(WallData wallData)
		{
			this.m_FindedPositive = wallData.FindedPositive;
			this.m_FindedPositiveLineSegments = wallData.m_FindedPositiveLineSegments;
			this.m_FindedNegative = wallData.FindedNegative;
			this.m_FindedNegativeLineSegments = wallData.m_FindedNegativeLineSegments;
		}

		public void AddPositiveFindedInfo(EdgeInfo findedSegment)
		{
			this.m_FindedPositive = true;
			this.m_FindedPositiveLineSegments.Add(findedSegment);
		}

		public void AddNegativeFindedInfo(EdgeInfo findedSegment)
		{
			this.m_FindedNegative = true;
			this.m_FindedNegativeLineSegments.Add(findedSegment);
		}

		public bool Linked(WallData wallData)
		{
			return this.CenterLine.StartPoint.IsAlmostEqualTo(wallData.CenterLine.StartPoint) || this.CenterLine.StartPoint.IsAlmostEqualTo(wallData.CenterLine.EndPoint) || this.CenterLine.EndPoint.IsAlmostEqualTo(wallData.CenterLine.StartPoint) || this.CenterLine.EndPoint.IsAlmostEqualTo(wallData.CenterLine.EndPoint);
		}

		public bool GetOrientationOuterWall(ref XYZ orientation)
		{
			WallData.OutWallOrientations outWallOrientations = WallData.OutWallOrientations.OWO_None;
			if (!this.IsOutWall(ref outWallOrientations))
			{
				return false;
			}
			if (this.m_PositiveLine.IsArc)
			{
				XYZ xyz = XYZ.BasisZ;
				if (Geometry.LessThan(this.m_PositiveLine.Bulge, 0.0))
				{
					xyz = -xyz;
				}
				XYZ ptCenter = null;
				Geometry.GetCenterWithBulge(this.m_PositiveLine.StartPoint, this.m_PositiveLine.EndPoint, this.m_PositiveLine.Bulge, ref ptCenter);
				XYZ xyz2 = Geometry.CalculatMidPoint(this.m_PositiveLine.StartPoint, this.m_PositiveLine.EndPoint, ptCenter, xyz);
				XYZ xyz3 = Geometry.CalculatMidPoint(this.m_NegativeLine.StartPoint, this.m_NegativeLine.EndPoint, ptCenter, xyz);
				if (this.m_FindedPositive)
				{
					orientation = (xyz3 - xyz2).Normalize();
				}
				else if (this.m_FindedNegative)
				{
					orientation = (xyz2 - xyz3).Normalize();
				}
			}
			else if (this.m_FindedPositive)
			{
				orientation = (this.m_NegativeLine.StartPoint - this.m_PositiveLine.StartPoint).Normalize();
			}
			else if (this.m_FindedNegative)
			{
				orientation = (this.m_PositiveLine.StartPoint - this.m_NegativeLine.StartPoint).Normalize();
			}
			return true;
		}

		public bool IsOrientationRight(ref bool isOrientationRight)
		{
			WallData.OutWallOrientations outWallOrientations = WallData.OutWallOrientations.OWO_None;
			if (!this.IsOutWall(ref outWallOrientations))
			{
				return false;
			}
			Wall wall = null;
			try
			{
				wall = (this.Doc.GetElement(this.m_Id) as Wall);
			}
			catch (Exception)
			{
				return false;
			}
			if (wall == null)
			{
				return false;
			}
			XYZ pt;
			if (this.m_PositiveLine.IsArc)
			{
				XYZ xyz = XYZ.BasisZ;
				if (Geometry.LessThan(this.m_PositiveLine.Bulge, 0.0))
				{
					xyz = -xyz;
				}
				XYZ xyz2 = null;
				Geometry.GetCenterWithBulge(this.m_PositiveLine.StartPoint, this.m_PositiveLine.EndPoint, this.m_PositiveLine.Bulge, ref xyz2);
				if (this.m_FindedPositive)
				{
					pt = (this.m_PositiveLine.StartPoint - xyz2).Normalize();
				}
				else if (this.m_FindedNegative)
				{
					pt = (xyz2 - this.m_PositiveLine.StartPoint).Normalize();
				}
				else
				{
					pt = wall.Orientation;
				}
			}
			else if (this.m_FindedPositive)
			{
				pt = (this.m_NegativeLine.StartPoint - this.m_PositiveLine.StartPoint).Normalize();
			}
			else if (this.m_FindedNegative)
			{
				pt = (this.m_PositiveLine.StartPoint - this.m_NegativeLine.StartPoint).Normalize();
			}
			else
			{
				pt = wall.Orientation;
			}
			isOrientationRight = false;
			if (Geometry.IsEqual(pt, wall.Orientation))
			{
				isOrientationRight = true;
			}
			return true;
		}

		private EdgeInfo m_PositiveLine;

		private EdgeInfo m_NegativeLine;

		private EdgeInfo m_CenterLine;

		private Document m_Doc;

		private ElementId m_Id;

		private bool m_FindedPositive;

		private List<EdgeInfo> m_FindedPositiveLineSegments = new List<EdgeInfo>();

		private bool m_FindedNegative;

		private List<EdgeInfo> m_FindedNegativeLineSegments = new List<EdgeInfo>();

		public enum OutWallOrientations : uint
		{
			OWO_None,
			OWO_Positive,
			OWO_Negative,
			OWO_Two_Sided
		}
	}
}
